﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

using System.Web.Mvc.Html;
using SpyApp.Models;
using System.Collections.Specialized;
using SpyApp.Models.BaseCommon.Enum;

namespace SpyApp.Helpers
{
    public static class HtmlHelperExtensions
    {
        #region Html Helper
        //Html.ActionLink()
        //Html.BeginForm()
        //Html.CheckBox()
        //Html.DropDownList()
        //Html.EndForm()
        //Html.Hidden()
        //Html.ListBox()
        //Html.Password()
        //Html.RadioButton()
        //Html.TextArea()
        //Html.TextBox()

        /// <summary> Img tag </summary>
        public static MvcHtmlString _Img(this HtmlHelper htmlHelper, string src, string altText)
        {
            var builder = new TagBuilder("img");
            builder.MergeAttribute("src", src);
            builder.MergeAttribute("alt", altText);
            return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
        }

        /// <summary> Lable tag </summary>
        public static string _Label(string target, string text)
        {
            return String.Format("<label for='{0}'>{1}</label>", target, text);
        }

        /// <summary> input submit tag </summary>
        public static MvcHtmlString _SubmitButton(this HtmlHelper htmlHelper, string buttonText)
        {
            string str = "<input type=\"submit\" value=\"" + buttonText + "\" />";
            return new MvcHtmlString(str);
        }

        /// <summary>  
        /// Display Name for IEnumerable in object 
        /// Hiển thị tên của object
        /// </summary>
        public static MvcHtmlString _DisplayNameFor<TModel, TClass, TProperty>(this HtmlHelper<TModel> helper, IEnumerable<TClass> model, Expression<Func<TClass, TProperty>> expression)
        {
            var name = ExpressionHelper.GetExpressionText(expression);
            name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
            var metadata = ModelMetadataProviders.Current.GetMetadataForProperty(
                () => Activator.CreateInstance<TClass>(), typeof(TClass), name);

            var returnName = metadata.DisplayName;
            if (string.IsNullOrEmpty(returnName))
                returnName = metadata.PropertyName;

            return new MvcHtmlString(returnName);
        }

        /// <summary> Textbox + placeholder </summary>
        public static MvcHtmlString _TextBoxPlaceHolderFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, IDictionary<string, object> htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
            string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
            if (!String.IsNullOrEmpty(labelText))
            {
                if (htmlAttributes == null)
                {
                    htmlAttributes = new Dictionary<string, object>();
                }
                htmlAttributes.Add("placeholder", labelText);
            }
            return html.TextBoxFor(expression, htmlAttributes);
        }

        /// <summary> Checkboxlist for //  chưa làm </summary>
        public static MvcHtmlString _CheckBoxListFor<TModel, TClass, TProperty>(this HtmlHelper<TModel> html, TClass model, Expression<Func<TClass, IEnumerable<String>>> expression, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes)
        {
            return new MvcHtmlString("");
        }

        #region Pageing
        /// <summary> PageList to Page 
        /// using @Html._PageListPager(Request.QueryString, Model, new SpyApp.Models.CustomPageListRenderOption(), null)
        /// </summary>
        public static MvcHtmlString _PageListPager(this HtmlHelper htmlHelper, NameValueCollection queryString, CustomPageList model, CustomPageListRenderOption options, IDictionary<string, object> htmlAttributes)
        {
            #region init
            RouteValueDictionary routeValue = queryString._ToRouteValueDictionary(); // convert to add
            TagBuilder ulContain = new TagBuilder("ul");
            ulContain.AddCssClass(options.ContainClasses);
            int pageIndex = model.PageIndex;
            int pageCount = model.PageCount;
            #endregion

            #region body
            // first, after
            if (pageIndex > 1)
            {
                ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, options.PreviousPageFormat, pageIndex - 1, new { @class = options.ItemClasses }).ToHtmlString();
            }
            // 1->[curr]
            if (pageIndex <= 4)
            {
                //123[4]
                for (int i = 1; i < pageIndex - 1; i++)
                {
                    ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, i.ToString(), i, new { @class = options.ItemClasses }).ToHtmlString();
                }
            }
            else
            {
                //1...34[5]
                ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, "1", 1, new { @class = options.ItemClasses }).ToHtmlString(); //1
                int gap1Index = pageIndex / 2;
                ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, options.GapPageFormat, gap1Index, new { @class = options.ItemClasses }).ToHtmlString(); //...
                for (int i = pageIndex - 2; i <= pageIndex - 1; i++)
                {
                    ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, i.ToString(), i, new { @class = options.ItemClasses }).ToHtmlString();
                }
            }
            //[curr]
            ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, pageIndex.ToString(), pageIndex, new { @class = options.ActiveClasses }).ToHtmlString();
            // [curr]->count
            if (pageIndex >= pageCount - 4)
            {
                //[-4]-3-2-1-0
                for (var i = pageIndex + 1; i <= pageCount; i++)
                {
                    ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, i.ToString(), i, new { @class = options.ItemClasses }).ToHtmlString();
                }
            }
            else
            {
                //[-6]-5-4-3...0
                for (var i = pageIndex + 1; i <= pageIndex + 2; i++)
                {
                    ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, i.ToString(), i, new { @class = options.ItemClasses }).ToHtmlString();
                }
                int gap2Index = (pageCount + pageIndex) / 2;
                ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, options.GapPageFormat, gap2Index, new { @class = options.ItemClasses }).ToHtmlString(); //...
                ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, pageCount.ToString(), pageCount, new { @class = options.ItemClasses }).ToHtmlString(); //last
            }

            // first, after
            if (pageIndex < pageCount)
            {
                ulContain.InnerHtml += _LiRouteLink(htmlHelper, routeValue, options.NextPageFormat, pageIndex + 1, new { @class = options.ItemClasses }).ToHtmlString(); //last
            }
            //display form [10] to [20] of [200] items
            string info = string.Format(options.ItemInfoFormat, model.Skip + 1, model.Skip + model.PageSize, model.TotalItemCount);
            ulContain.InnerHtml += _LiSpan(htmlHelper, info, null).ToHtmlString();
            #endregion

            return new MvcHtmlString(ulContain.ToString(TagRenderMode.Normal));
        }

        /// <summary> Support Page list </summary>
        public static MvcHtmlString _LiRouteLink(this HtmlHelper htmlHelper, RouteValueDictionary routeValue, string linkText, int pageIndex, object htmlAttributes)
        {
            //li
            TagBuilder liContain = new TagBuilder("li");
            liContain.MergeAttributes(new RouteValueDictionary(htmlAttributes)); // add attributes
            //a
            routeValue = routeValue._AddOrUpdate(StaticValue.CURRENT_PAGE, pageIndex); // update route + page value
            var routeLink = htmlHelper.RouteLink(linkText, routeValue);
            //add
            liContain.InnerHtml += routeLink.ToHtmlString();
            return new MvcHtmlString(liContain.ToString(TagRenderMode.Normal));
        }

        /// <summary> Support Page list </summary>
        public static MvcHtmlString _LiSpan(this HtmlHelper htmlHelper, string innerText, object htmlAttributes)
        {
            //li
            TagBuilder liContain = new TagBuilder("li");
            liContain.MergeAttributes(new RouteValueDictionary(htmlAttributes)); // add attributes
            //span
            TagBuilder span = new TagBuilder("span");
            span.InnerHtml = innerText;
            //add
            liContain.InnerHtml += span.ToString(TagRenderMode.Normal);
            return new MvcHtmlString(liContain.ToString(TagRenderMode.Normal));
        }

        #endregion
        #endregion
    }
}